package com.luo.d3s.core.infrastructure.convertor;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.luo.d3s.core.application.dto.PageQuery;
import com.luo.d3s.core.application.dto.PageResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Spring Data Page分页转换
 *
 * @author luohq
 * @date 2023-07-26
 */
public interface JpaPageConvertor {

    /**
     * 转换PageQuery为Spring Data分页参数
     *
     * @param pageQuery 分页查询参数
     * @return Spring Data分页参数
     */
    static Pageable toPage(PageQuery pageQuery) {
        //Spring Data PageIndex从0开始
        PageRequest pageRequest = PageRequest.of(Math.max(pageQuery.getPageIndex() - 1, 0), pageQuery.getPageSize());
        if (StringUtils.hasText(pageQuery.getOrderBy())) {
            Sort sort = PageQuery.ASC.equals(pageQuery.getOrderDirection())
                    ? Sort.by(pageQuery.getOrderBy()).ascending()
                    : Sort.by(pageQuery.getOrderBy()).descending();
            pageRequest = pageRequest.withSort(sort);
        }
        return pageRequest;
    }

    /**
     * 转换Spring Data分页查询结果为PageResponse
     *
     * @param pageResult Spring Data分页查询结果
     * @param <T>        实体类型
     * @return PageResponse
     */
    static <T> PageResponse<T> toPageResponse(Page<T> pageResult) {
        return PageResponse.of(pageResult.getContent(),
                Long.valueOf(pageResult.getTotalElements()).intValue(),
                pageResult.getPageable().getPageSize(),
                //Spring Data PageIndex从0开始
                pageResult.getPageable().getPageNumber() + 1);
    }

    /**
     * 转换Spring Data分页查询结果为PageResponse
     *
     * @param pageResult Spring Data分页查询结果
     * @param convertor  实体转换器
     * @param <T>        源实体类型
     * @param <R>        目标实体类型
     * @return PageResponse
     */
    static <T, R> PageResponse<R> toPageResponse(Page<T> pageResult, Function<T, R> convertor) {
        List<R> resultList = Collections.emptyList();
        if (CollectionUtils.isNotEmpty(pageResult.getContent())) {
            resultList = pageResult.getContent().stream()
                    .map(convertor)
                    .collect(Collectors.toList());
        }
        return PageResponse.of(resultList,
                Long.valueOf(pageResult.getTotalElements()).intValue(),
                pageResult.getPageable().getPageSize(),
                //Spring Data PageIndex从0开始
                pageResult.getPageable().getPageNumber() + 1);
    }
}
